# -*- coding: utf-8 -*- #
import sys
code = sys.getdefaultencoding()
if code != 'utf8':
	reload(sys)
	sys.setdefaultencoding('utf8')

import logging
logging.logMultiprocessing = 0

import os, urllib, uuid, md5, datetime, time
from xml.dom import minidom

from django.utils import simplejson as json

from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template

from google.appengine.api import memcache
from google.appengine.api import urlfetch

#begin global variables
sync_frame = datetime.timedelta(0, 3600)


#begin cron tasks
class SessionExpirer(webapp.RequestHandler):
	def get(self):
		global sync_frame
		now = datetime.datetime.now()
		#find online sessions
		query = UserSession.gql("WHERE timestamp < :1 AND online=:2", now - sync_frame,True)
		sessions = query.fetch(1000) #at most 1000 sessions per expirer
		inf = 'expire %d sessions' % (len(sessions))
		logging.info(inf)
		for ses in sessions:
			v = memcache.get(ses.sessionkey)
			if v is not None:
				#refresh session
				ses.timestamp = now
				ses.put()
			else:
				#expire session
				ses.online = False
				ses.put()


#begin domains
class UserSession(db.Model):
	timestamp = db.DateTimeProperty(auto_now_add = True)
	sessionkey = db.StringProperty()
	uid = db.StringProperty()
	groupid = db.IntegerProperty(default=0)
	online = db.BooleanProperty(default=False)

class ChatMsg(db.Model):
	timestamp = db.DateTimeProperty(auto_now_add = True)
	seq = db.IntegerProperty()
	sender = db.StringProperty()
	to = db.StringProperty()
	content = db.StringProperty(multiline=True)
	isread = db.BooleanProperty(default=False)

#end domains


#begin probe
class NewSession(webapp.RequestHandler):
	def get(self):
		callback = self.request.get('callback')
		uid = self.request.get('uid')
		if callback =='' or uid=='':
			self.response.out.write('<script>alert("need callback and uid")</script>')
			return

		seskey = self.request.get('session')

		q = UserSession.gql("WHERE uid=:1",uid)
		results = q.fetch(1)
		#if have prev session, then return exists
		if results is not None and len(results) > 0:
			ses = results[0]
#			if seskey is None or seskey =='':
#				res = {'status':0}	#already exists
#			else:
#				ses = results[0]
#				if seskey == ses.sessionkey:
#					res = {'status':1,'session':skey} #matched
#				else:
#					res = {'status':0}	#not matched
			res = {'status':1,'session':ses.sessionkey} #matched
		else:
			#not exists
			skey = str(uuid.uuid1())
			#add session record to db, used to userlist
			newSession = UserSession(uid=uid,sessionkey=skey,online=True)
			newSession.put()
			memcache.add(skey,uid,3600) #add session to memcache,used to update and expiration
			res = {'status':1,'session':skey}
		outData = "%s(%s)" % (callback, json.dumps(res))
		self.response.out.write(outData)


class MsgDetect(webapp.RequestHandler):
	def get(self):
		callback = self.request.get('callback')
		seskey = self.request.get('session')
		if callback=='' or seskey=='':
			self.response.out.write('<script>alert("need callback and session")</script>')
			return

		q = UserSession.gql("WHERE sessionkey=:1",seskey)
		results = q.fetch(1)
		if results is not None and len(results) > 0:
			session = results[0]
			uid = session.uid
			memcache.replace(seskey,uid,3600) #update mem session
			q = ChatMsg.gql("WHERE to=:1 AND isread=false ORDER BY timestamp ASC", uid)
			msgs = q.fetch(1)
			if len(msgs) > 0:
				sender = msgs[0].sender
				res = {'uin':uid,'status':1,'sender':sender}
			else:
				res = {'status':0}
		else:
			res = {'status':-1}

		self.response.out.write( ("%s(%s)" % (callback,json.dumps(res))) )
#end probe


class Liss(webapp.RequestHandler):
	def get(self):
		cmd = self.request.get('cmd')
		if cmd=="session":
			self.response.out.write( str(uuid.uuid1()) )
			ses = UserSession(
				sessionkey= str(uuid.uuid1()),
				uid='user1'
			)
			ses.put()
			for ses in UserSession.all():
				s = "<li>%s,%s</li>" % (ses.uid, ses.sessionkey)
				self.response.out.write(s)

		if cmd=="flist":
			userlistProxy = "http://blog.chinaanxu.com/get_online_users.asp"
			result = urlfetch.fetch(url=userlistProxy, method=urlfetch.GET)
			self.response.out.write(result.content)



class Chatty(webapp.RequestHandler):
	def __init__(self):
		self.userlistProxy = "http://blog.chinaanxu.com/get_online_users.asp"


	def get(self):
		to = self.request.get('to')
		msgs = ChatMsg.gql("WHERE to=:1 ORDER BY timestamp ASC", to)
		for msg in msgs:
			#print time.mktime(msg.timestamp.timetuple())
			print "<script>alert(decodeURIComponent('%s') )</script>" % (msg.content.encode('gbk'))

	def fetch_msgs(self,uin):
		#max 20 msgs
		msgs = db.GqlQuery("SELECT * FROM ChatMsg WHERE to=:1 AND isread=false ORDER BY timestamp ASC", uin).fetch(20)
		return msgs

	def delete_msgs(self,msgs):
		db.delete(msgs)

	def mark_msgs(self,msgs):
		for msg in msgs:
			msg.isread = True
			msg.put()


	def post(self):
		data = self.request.body.decode('utf-8')
		objs = json.loads(data)
		
		touchSessionOnce = False
		resPkgs = []
		for obj in objs:
			cmd = obj['cmd']
			seq = obj['seq']
			myid = obj['uin']
			seskey = obj['session']
			if touchSessionOnce == False:
				memcache.replace(seskey,myid,3600) #update mem session
				touchSessionOnce = True

			if cmd == '58':
				try:
					#result = urlfetch.fetch(url=self.userlistProxy, method=urlfetch.GET)
					#resObj = json.loads(result.content.decode('gbk').encode('utf-8'))
					#userlist = resObj['rows']
					#userlist2 = []
					#for user in userlist:
					#	uin = ''.join([user['l_username'],'(',str(user['l_id']),')'])
					#	user1 = {'uin': uin, 'group_id' : '_1000'}
					#	userlist2.append(user1)
					userlist = []
					q = UserSession.gql('WHERE online=:1',True)
					for ses in q:
						if ses.groupid == 0:ses.groupid=1000
						user = {'uin': ses.uid, 'group_id' : ses.groupid}
						userlist.append(user)
					userlist.append({'uin': 'MJ', 'group_id' : 999})
					s = 'fetch userlist(%d online users)' % (len(userlist))
					logging.info(s)
					resPkg = {'seq':seq,'cmd':'58', 'body': userlist}
					resPkgs.append(resPkg)		
				except Exception,e:
					print e
			elif cmd == '00':
				msgs = self.fetch_msgs(myid)
				if msgs is not None and len(msgs) > 0:
					for msg in msgs:
						msgObj = {'content':msg.content,'to':myid,'sender':msg.sender,'timestamp':time.mktime(msg.timestamp.timetuple())}
						resPkg = {'cmd':'17','seq':msg.seq,'body':msgObj}
						resPkgs.append(resPkg)
					self.mark_msgs(msgs)
				else:
					#heartbeat if necesary
					resPkg = {'cmd':'00','seq':seq,'body':''}
					resPkgs.append(resPkg)
			elif cmd == '01':
				#get login info
				pass
			elif cmd == '16':
				msg = json.loads(obj['body'])
				dbmsg = ChatMsg(
					content=urllib.unquote(msg['msg'].encode('utf-8')),
					to=msg['to'],
					sender=obj['uin'],
					seq=obj['seq']
				)
				dbmsg.put()
				resPkg = {'cmd':'16','seq':seq,'body':''}
				resPkgs.append(resPkg)
				#send msg
			elif cmd == '1234':
				session = obj['body']
				result = UserSession.gql('WHERE sessionkey=:1',session).fetch(1)
				db.delete(result)
					
		self.response.out.write(json.dumps(resPkgs))
		#{'res':'ok', 'cmd': 11, 'seq':$reqObj->seq}
		#res = {'res':'ok', 'cmd': 11, 'seq':1}
		#self.response.headers['Content-Type'] = 'text/plain'
		#self.response.out.write(json.dumps(res))
